home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / VMSMAIN.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  10KB  |  436 lines

  1. /*    SCCS Id: @(#)vmsmain.c    3.0    89/01/13
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4. /* main.c - VMS NetHack */
  5.  
  6. #include "hack.h"
  7.  
  8. #include <signal.h>
  9.  
  10. char SAVEF[PL_NSIZ + 20];            /* [.save]<uic>player;1 */
  11.  
  12. const char *hname = 0;        /* name of the game (argv[0] of call) */
  13. char obuf[BUFSIZ];    /* BUFSIZ is defined in stdio.h */
  14. int hackpid = 0;                /* current pid */
  15. int locknum = 0;                /* max num of players */
  16.  
  17. static void NDECL(whoami);
  18. static void NDECL(byebye);
  19. #ifndef SAVE_ON_FATAL_ERROR
  20. static long FDECL(vms_handler,(long [],long []));
  21. #include <ssdef.h>      /* system service status codes */
  22. #endif
  23.  
  24. int
  25. main(argc,argv)
  26. int argc;
  27. char *argv[];
  28. {
  29.     extern int x_maze_max, y_maze_max;
  30.     register int fd;
  31. #ifdef CHDIR
  32.     register char *dir;
  33. #endif
  34.  
  35.     atexit(byebye);
  36.     hname = argv[0];
  37.     hackpid = getpid();
  38.     (void) umask(0);
  39.  
  40.     /*
  41.      *  Remember tty modes, to be restored on exit.
  42.      *
  43.      *  gettty() must be called before startup()
  44.      *    due to ordering of LI/CO settings
  45.      *  startup() must be called before initoptions()
  46.      *    due to ordering of graphics settings
  47.      */
  48.     gettty();
  49.     setbuf(stdout,obuf);
  50.     startup();
  51.     initoptions();
  52.     whoami();
  53.  
  54. #ifdef CHDIR            /* otherwise no chdir() */
  55.     /*
  56.      * See if we must change directory to the playground.
  57.      * (Perhaps hack is installed with privs and playground is
  58.      *  inaccessible for the player.)
  59.      * The logical name HACKDIR is overridden by a
  60.      *  -d command line option (must be the first option given)
  61.      */
  62.     dir = getenv("HACKDIR");
  63. #endif
  64.     if(argc > 1) {
  65. #ifdef CHDIR
  66.         if (!strncmp(argv[1], "-d", 2) && argv[1][2] != 'e') {
  67.         /* avoid matching "-dec" for DECgraphics; since the man page
  68.          * says -d directory, hope nobody's using -desomething_else
  69.          */
  70.         argc--;
  71.         argv++;
  72.         dir = argv[0]+2;
  73.         if(*dir == '=' || *dir == ':') dir++;
  74.         if(!*dir && argc > 1) {
  75.             argc--;
  76.             argv++;
  77.             dir = argv[0];
  78.         }
  79.         if(!*dir)
  80.             error("Flag -d must be followed by a directory name.");
  81.         } else
  82. #endif /* CHDIR /**/
  83.  
  84.     /*
  85.      * Now we know the directory containing 'record' and
  86.      * may do a prscore().
  87.      */
  88.         if (!strncmp(argv[1], "-s", 2)) {
  89. #ifdef CHDIR
  90.         chdirx(dir,0);
  91. #endif
  92.         prscore(argc, argv);
  93.         if(isatty(1) > 0) getret();
  94.         settty(NULL);
  95.         exit(0);
  96.         }
  97.     }
  98.  
  99.     /*
  100.      * It seems you really want to play.
  101.      */
  102.     setrandom();
  103.     cls();
  104.     u.uhp = 1;    /* prevent RIP on early quits */
  105.     u.ux = FAR;    /* prevent nscr() */
  106. #ifndef SAVE_ON_FATAL_ERROR
  107.     /* used to clear hangup stuff while still giving standard traceback */
  108.     VAXC$ESTABLISH(vms_handler);
  109. #endif
  110.     (void) signal(SIGHUP, (SIG_RET_TYPE) hangup);
  111.  
  112.     /*
  113.      * Find the creation date of this game,
  114.      * so as to avoid restoring outdated savefiles.
  115.      */
  116.     gethdate(hname);
  117.  
  118.     /*
  119.      * We cannot do chdir earlier, otherwise gethdate will fail.
  120.      */
  121. #ifdef CHDIR
  122.     chdirx(dir,1);
  123. #endif
  124.  
  125.     /*
  126.      * Process options.
  127.      */
  128.     while(argc > 1 && argv[1][0] == '-'){
  129.         argv++;
  130.         argc--;
  131.         switch(argv[0][1]){
  132. #if defined(WIZARD) || defined(EXPLORE_MODE)
  133. # ifndef EXPLORE_MODE
  134.         case 'X':
  135.         case 'x':
  136. # endif
  137.         case 'D':
  138. # ifdef WIZARD
  139.             if(!strcmp(getenv("USER"), WIZARD_NAME)) {
  140.                 wizard = TRUE;
  141.                 break;
  142.             }
  143.             /* otherwise fall thru to discover */
  144. # endif
  145. # ifdef EXPLORE_MODE
  146.         case 'X':
  147.         case 'x':
  148.             discover = TRUE;
  149. # endif
  150.             break;
  151. #endif
  152. #ifdef NEWS
  153.         case 'n':
  154.             flags.nonews = TRUE;
  155.             break;
  156. #endif
  157.         case 'u':
  158.             if(argv[0][2])
  159.               (void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
  160.             else if(argc > 1) {
  161.               argc--;
  162.               argv++;
  163.               (void) strncpy(plname, argv[0], sizeof(plname)-1);
  164.             } else
  165.                 Printf("Player name expected after -u\n");
  166.             break;
  167.         case 'i':
  168.             if(!strcmp(argv[0]+1, "ibm")) assign_ibm_graphics();
  169.             break;
  170.         case 'd':
  171.             if(!strcmp(argv[0]+1, "dec")) assign_dec_graphics();
  172.             break;
  173.         default:
  174.             /* allow -T for Tourist, etc. */
  175.             (void) strncpy(pl_character, argv[0]+1,
  176.                 sizeof(pl_character)-1);
  177.  
  178.             /* Printf("Unknown option: %s\n", *argv); */
  179.         }
  180.     }
  181.  
  182.     if(argc > 1)
  183.         locknum = atoi(argv[1]);
  184. #ifdef MAX_NR_OF_PLAYERS
  185.     if(!locknum || locknum > MAX_NR_OF_PLAYERS)
  186.         locknum = MAX_NR_OF_PLAYERS;
  187. #endif
  188. #ifdef WIZARD
  189.     if (wizard)
  190.         Strcpy(plname, "wizard");
  191.     else
  192. #endif
  193.     if(!*plname || !strncmp(plname, "games", 4))
  194.         askname();
  195.     plnamesuffix();        /* strip suffix from name; calls askname() */
  196.                 /* again if suffix was whole name */
  197.                 /* accepts any suffix */
  198. #ifdef WIZARD
  199.     if(!wizard) {
  200. #endif
  201.         /*
  202.          * check for multiple games under the same name
  203.          * (if !locknum) or check max nr of players (otherwise)
  204.          */
  205.         (void) signal(SIGQUIT,SIG_IGN);
  206.         (void) signal(SIGINT,SIG_IGN);
  207.         if(!locknum)
  208.             Sprintf(lock, "%d%s", getuid(), plname);
  209.         getlock();    /* sets lock if locknum != 0 */
  210. #ifdef WIZARD
  211.     } else
  212.         Sprintf(lock, "%d%s", getuid(), plname);
  213. #endif /* WIZARD /**/
  214.     setftty();
  215.  
  216.     /*
  217.      * Initialisation of the boundaries of the mazes
  218.      * Both boundaries have to be even.
  219.      */
  220.  
  221.     x_maze_max = COLNO-1;
  222.     if (x_maze_max % 2)
  223.         x_maze_max--;
  224.     y_maze_max = ROWNO-1;
  225.     if (y_maze_max % 2)
  226.         y_maze_max--;
  227.  
  228.     /* initialize static monster strength array */
  229.     init_monstr();
  230.  
  231.     Sprintf(SAVEF, "[.save]%d%s", getuid(), plname);
  232.     regularize(SAVEF+7);    /* avoid bogus chars in name */
  233.     if((fd = open(SAVEF,O_RDONLY)) >= 0 &&
  234.        /* if not up-to-date, quietly unlink file via false condition */
  235.        (uptodate(fd) || unlink(SAVEF) >= 0)) {
  236. #ifdef WIZARD
  237.         /* Since wizard is actually flags.debug, restoring might
  238.          * overwrite it.
  239.          */
  240.         boolean remember_wiz_mode = wizard;
  241. #endif
  242.         (void) chmod(SAVEF,0);    /* disallow parallel restores */
  243.         (void) signal(SIGINT, (SIG_RET_TYPE) done1);
  244.         pline("Restoring save file...");
  245.         (void) fflush(stdout);
  246.         if(!dorecover(fd))
  247.             goto not_recovered;
  248. #ifdef WIZARD
  249.         if(!wizard && remember_wiz_mode) wizard = TRUE;
  250. #endif
  251.         pline("Hello %s, welcome to NetHack!", plname);
  252.         /* get shopkeeper set properly if restore is in shop */
  253.         (void) inshop();
  254. #ifdef EXPLORE_MODE
  255.         if (discover)
  256.             You("are in non-scoring discovery mode.");
  257. #endif
  258. #if defined(EXPLORE_MODE) || defined(WIZARD)
  259.         if (discover || wizard) {
  260.             pline("Do you want to keep the save file? ");
  261.             if(yn() == 'n')
  262.                 (void) unlink(SAVEF);
  263.             else
  264.                 (void) chmod(SAVEF,FCMASK); /* back to readable */
  265.         }
  266. #endif
  267.         flags.move = 0;
  268.     } else {
  269. not_recovered:
  270.         newgame();
  271.         /* give welcome message before pickup messages */
  272.         pline("Hello %s, welcome to NetHack!", plname);
  273. #ifdef EXPLORE_MODE
  274.         if (discover)
  275.             You("are in non-scoring discovery mode.");
  276. #endif
  277.         flags.move = 0;
  278.         set_wear();
  279.         pickup(1);
  280.         read_engr_at(u.ux,u.uy);
  281.     }
  282.  
  283.     flags.moonphase = phase_of_the_moon();
  284.     if(flags.moonphase == FULL_MOON) {
  285.         You("are lucky!  Full moon tonight.");
  286.         if(!u.uluck) change_luck(1);
  287.     } else if(flags.moonphase == NEW_MOON) {
  288.         pline("Be careful!  New moon tonight.");
  289.     }
  290.  
  291.     initrack();
  292.  
  293.     moveloop();
  294.     return(0);
  295. }
  296.  
  297. void
  298. glo(foo)
  299. register int foo;
  300. {
  301.     /* construct the string  xlock.n  */
  302.     register char *tf;
  303.  
  304.     tf = lock;
  305.     while(*tf && *tf != '.') tf++;
  306.     Sprintf(tf, ".%d;1", foo);
  307. }
  308.  
  309. /*
  310.  * plname is filled either by an option (-u Player  or  -uPlayer) or
  311.  * explicitly (by being the wizard) or by askname.
  312.  * It may still contain a suffix denoting pl_character.
  313.  */
  314. void
  315. askname() {
  316.     register int c, ct;
  317.  
  318.     Printf("\nWho are you? ");
  319.     (void) fflush(stdout);
  320.     ct = 0;
  321.     while((c = getchar()) != '\n') {
  322.         if(c == EOF) error("End of input\n");
  323.         if(c != '-')
  324.         if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_';
  325.         if(ct < sizeof(plname)-1)
  326.             plname[ct++] = c;
  327.     }
  328.     plname[ct] = 0;
  329.     if(ct == 0) askname();
  330. }
  331.  
  332. #ifdef CHDIR
  333. void
  334. chdirx(dir, wr)
  335. char *dir;
  336. boolean wr;
  337. {
  338. # ifndef HACKDIR
  339.     static char *defdir = ".";
  340. # else
  341.     static char *defdir = HACKDIR;
  342.  
  343.     if(dir == NULL)
  344.         dir = defdir;
  345.     else if (wr)
  346.         /* If we're playing anywhere other than HACKDIR, turn off any
  347.            privs we may have been installed with. */
  348.         privoff();
  349. # endif
  350.  
  351.     if(dir && chdir(dir) < 0) {
  352.         perror(dir);
  353.         error("Cannot chdir to %s.", dir);
  354.     }
  355.  
  356.     /* warn the player if we can't write the record file */
  357.     /* perhaps we should also test whether . is writable */
  358.     /* unfortunately the access systemcall is worthless */
  359.     if(wr) {
  360.         register int fd;
  361.  
  362.         if(dir == NULL)
  363.         dir = "";
  364.         if((fd = open(RECORD, O_RDWR)) < 0) {
  365.         if((fd = open(RECORD, O_CREAT|O_RDWR, FCMASK)) < 0) {
  366.             Printf("Warning: cannot write %s/%s", dir, RECORD);
  367.             getret();
  368.         } else
  369.             (void) close(fd);
  370.         } else
  371.         (void) close(fd);
  372.     }
  373.     defdir = dir;
  374. }
  375. #endif /* CHDIR /**/
  376.  
  377. static void
  378. whoami() {
  379.     /*
  380.      * Who am i? Algorithm: 1. Use name as specified in NETHACKOPTIONS
  381.      *            2. Use $USER    (if 1. fails)
  382.      * The resulting name is overridden by command line options.
  383.      * If everything fails, or if the resulting name is some generic
  384.      * account like "games" then eventually we'll ask him.
  385.      * Note that we trust the user here; it is possible to play under
  386.      * somebody else's name.
  387.      */
  388.     register char *s;
  389.  
  390.     if(!*plname && (s = getenv("USER")))
  391.         (void) strncpy(plname, s, sizeof(plname)-1);
  392. }
  393.  
  394. static void
  395. byebye()
  396. {
  397.     int (*hup)();
  398. #ifdef SHELL
  399.     extern unsigned int dosh_pid;
  400.  
  401.     if (dosh_pid)
  402.     SYS$DELPRC(&dosh_pid, 0);
  403. #endif SHELL
  404.  
  405.     /* SIGHUP doesn't seem to do anything on VMS, so we fudge it here... */
  406.     hup = signal(SIGHUP, SIG_IGN);
  407.     if (hup != SIG_DFL && hup != SIG_IGN)
  408.     (*hup)();
  409.  
  410. #ifdef CHDIR
  411.     (void) chdir(getenv("PATH"));
  412. #endif
  413. }
  414.  
  415. #ifndef SAVE_ON_FATAL_ERROR
  416. /* Condition handler to prevent byebye's hangup simulation
  417.    from saving the game after a fatal error has occurred.  */
  418. static long
  419. vms_handler(sigargs, mechargs)
  420. long sigargs[], mechargs[];     /* [0] is argc, [1..argc] are the real args */
  421. {
  422.     extern boolean hu;          /* src/save.c */
  423.     long condition = sigargs[1];
  424.  
  425.     if (condition == SS$_ACCVIO         /* access violation */
  426.      || condition >= SS$_ASTFLT && condition <= SS$_TBIT
  427.      || condition >= SS$_ARTRES && condition <= SS$_INHCHME) {
  428.     if (wizard)
  429.         abort();    /* enter the debugger */
  430.     else
  431.         hu = TRUE;  /* pretend that hangup has already been attempted */
  432.     }
  433.     return SS$_RESIGNAL;
  434. }
  435. #endif
  436.